package com.cloud.class04.test;

import java.util.concurrent.CountDownLatch;

public class CountDawnLatchExample {
//    CountDownLatch是java中的一个同步工具类，它允许一个或多个线程等待直到在
//    其他线程中执行的一组操作完成。
//    举一个例子，三个同学，一个买面，一个买饭，一个买馒头，最后一起回宿舍。
//    CyclicBarrier
//    实现思路：
//    1、创建一个CountDownLatch对象，初始技术器设置为3。
//    2、创建三个线程，分别表示三个同学买面、买饭、买馒头。
//    3、在每个线程中执行购买食物的操作，然后调用countDownLatch.countDown()方法
//    将计数器减1，表示一个线程完成购买操作。
//    4、在主线程中调用await()方法等待计数器为0，表示所有线程都完成购买操作（所有人购买完一起回宿舍）。

    public static void main(String[] args) throws InterruptedException {
        //创建一个CountDownLatch对象，初始计数器设置为3。
        CountDownLatch countDawnLatch = new CountDownLatch(3);

//        创建三个同学的线程
        new Thread(new Student(countDawnLatch, "买面")).start();
        new Thread(new Student(countDawnLatch, "买饭")).start();
        new Thread(new Student(countDawnLatch, "买馒头")).start();


//        主线程等待计数器变为0，表示所有线程都完成购买操作（所有人购买完一起回宿舍）。
//        await()方法会阻塞当前线程，直到计数器变为0，才继续执行。
        countDawnLatch.await();
        System.out.println("所有人购买完一起回宿舍");
    }
}
class Student implements Runnable {
    private String task;
    private CountDownLatch countDawnLatch;

    public Student(CountDownLatch countDawnLatch, String task) {
        this.countDawnLatch = countDawnLatch;
        this.task = task;
    }

    @Override
    public void run() {
//        模拟购买食物的操作
        System.out.println(Thread.currentThread().getName() + "开始购买" + task);
        try {
            Thread.sleep((long) (Math.random() * 1000));
            //        完成任务后，计数器减1
            countDawnLatch.countDown();
        } catch (InterruptedException e) {
//            throws： 对应于“下游治污”，表明某个方法在执行过程中可能会产生特定类型的异常，
//            但并不在该方法内部处理，而是将责任转移给调用者（下游）去处理这些潜在的“污染”。
//
//            throw： 对应于“上游排污”，意味着在程序执行流程中某个具体的点（通常是方法内部），
//            直接抛出一个已创建的异常对象。这个动作就像上游排放污染物一样，主动触发了异常的发生
            throw new RuntimeException(e);
        }

    }
}


//class Person extends Thread{
//    @Override
//    public void run() {
//        super.run();
//    }
//}
